
module es {
    /**
     * Class ThirdSupport 
     * 
     * .You can inherit it to gain the ability to dispatch events
     * 
     * @anchor ChenJC | Geek7
     * @date 20220615
     */
    export class ThirdSupport {

        protected persistentHandler: Map<string, es.Functor[]> = new Map<string, es.Functor[]>();
        protected onceHandler: Map<string, es.Functor[]> = new Map<string, es.Functor[]>();


        on(eventType: string, caller: any, fn: Function) {

            if (this.persistentHandler.has(eventType)) {
                let handler = this.persistentHandler.get(eventType).find(f => f.equal2(caller, fn));
                if (null != handler) {
                    es.Debug.log(`$$$$$$$$$$ handler already listen: ${handler.toString()}`, "#ffff00");
                }
            }
            else {
                this.persistentHandler.set(eventType, [es.Functor.New(fn, caller)]);
            }
        }

        once(eventType: string, caller: any, fn: Function) {
            if (this.onceHandler.has(eventType)) {
                let handler = this.onceHandler.get(eventType).find(f => f.equal2(caller, fn));
                if (null != handler) {
                    es.Debug.log(`$$$$$$$$$$ handler already listen: ${handler.toString()}`, "#ffff00");
                }
            }
            else {
                this.onceHandler.set(eventType, [es.Functor.New(fn, caller)]);
            }
        }

        event(eventType: string) {
            if (this.persistentHandler.has(eventType)) {
                var handerArr = this.persistentHandler.get(eventType);
                for (let handler of handerArr) {
                    handler.invoke();
                }
            }

            if (this.onceHandler.has(eventType)) {
                var handerArr = this.onceHandler.get(eventType);
                for (let handler of handerArr) {
                    handler.invoke();
                }
            }
        }

        eventArgs(eventType: string, ...args) {
            if (this.persistentHandler.has(eventType)) {
                var handerArr = this.persistentHandler.get(eventType);
                for (let handler of handerArr) {
                    handler.invokeArgs(...args);
                }
            }

            if (this.onceHandler.has(eventType)) {
                var handerArr = this.onceHandler.get(eventType);
                for (let handler of handerArr) {
                    handler.invokeArgs(...args);
                }
            }
        }

        /**
         * 
         * @param eventType if this value is null, then delete all handelr for caller 
         * @param caller if this value is null and eventType is null, then clear all handler 
         * @param fn if this value is null, then clear caller all method.
         */
        off(eventType: string = null, caller: any = null, fn: Function = null) {

            if (eventType == null) {

                if (!caller) {
                    this.persistentHandler.clear();
                    this.onceHandler.clear();
                }
                else {
                    this.persistentHandler.forEach(arr => {
                        for (let i = 0; i < arr.length; i++) {
                            if (arr[i].getCaller() == caller && (arr[i].getMethod() == fn || !fn)) {
                                arr.splice(i--, 1);
                            }
                        }
                    });
                    this.onceHandler.forEach(arr => {
                        for (let i = 0; i < arr.length; i++) {
                            if (arr[i].getCaller() == caller && (arr[i].getMethod() == fn || !fn)) {
                                arr.splice(i--, 1);
                            }
                        }
                    });
                }

            }
            else {

                if (this.persistentHandler.has(eventType)) {
                    let arr = this.persistentHandler.get(eventType);
                    for (let i = 0; i < arr.length; i++) {
                        if (arr[i].getCaller() == caller && (!fn || fn == arr[i].getMethod())) {
                            arr.splice(i--,1);
                        }
                    }
                }

                if (this.onceHandler.has(eventType)) {
                    let arr = this.onceHandler.get(eventType);
                    for (let i = 0; i < arr.length; i++) {
                        if (arr[i].getCaller() == caller && (!fn || fn == arr[i].getMethod())) {
                            arr.splice(i--,1);
                        }
                    }
                }
            }
        }

    }

}